package com.junko.core.base;


import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.junko.model.PageForm;
import com.junko.model.BaseModel;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Repository("baseDao")
public class BaseDao<T extends BaseModel> extends SqlSessionDaoSupport implements Serializable {

    private static final long serialVersionUID = 7623507504198633838L;

    private final String POSTFIX = "Dao";
    private final String INSERT = ".insert";
    private final String INSERTSELECTIVE = ".insertSelective";
    private final String SELECTBYPRIMARYKEY = ".selectByPrimaryKey";
    private final String UPDATEBYPRIMARYKEY = ".updateByPrimaryKey";
    private final String UPDATEBYPRIMARYKEYSELECTIVE = ".updateByPrimaryKeySelective";
    private final String DELETEBYPRIMARYKEY = ".deleteByPrimaryKey";

    @Override
    @Autowired
    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        super.setSqlSessionFactory(sqlSessionFactory);
    }

    protected String getNameSpace() {
        Class<T> clazz = (Class) GenericsUtils.getSuperClassGenricType(this.getClass());

        return clazz.getName().replaceAll(".model.", ".dao.") + POSTFIX;
    }

    public int insert(T entity) {
        return getSqlSession().insert(this.getNameSpace() + INSERT, entity);
    }


    public int insertSelective(T record) {
        return getSqlSession().insert(this.getNameSpace() + INSERTSELECTIVE, record);
    }

    public T selectByPrimaryKey(Object id) {
        return getSqlSession().selectOne(this.getNameSpace() + SELECTBYPRIMARYKEY, id);
    }


    public int updateByPrimaryKey(T record) {
        return getSqlSession().update(this.getNameSpace() + UPDATEBYPRIMARYKEY, record);
    }

    public int updateByPrimaryKeySelective(T record) {
        return getSqlSession().update(this.getNameSpace() + UPDATEBYPRIMARYKEYSELECTIVE, record);
    }

    public int deleteByPrimaryKey(Object id) {
        return getSqlSession().delete(this.getNameSpace() + DELETEBYPRIMARYKEY, id);
    }

    public List<T> findTop(int top, String statementKey, Object parameter) {
        return getSqlSession().selectList(statementKey, getParam(parameter), new RowBounds(0, top));
    }

    public T findTopOne(String statementKey, Object parameter) {
        List<T> list = findTop(1, statementKey, parameter);
        return CollectionUtils.isEmpty(list) ? null : list.get(0);
    }

    public PageInfo<T> pageFind(String statementKey, PageForm pageForm, Object parameter) {
        PageHelper.startPage(pageForm.getPage(), pageForm.getRows());
        return new PageInfo(getSqlSession().selectList(statementKey, getParam(parameter)));
    }

    public <M> PageInfo<M> pageFindModel(String statementKey, PageForm pageForm, Object parameter) {
        PageHelper.startPage(pageForm.getPage(), pageForm.getRows());
        return new PageInfo(getSqlSession().selectList(statementKey, getParam(parameter)));
    }

    private Map getParam(Object parameter) {
        Map params = new HashMap();
        if (parameter != null) {
            if (parameter instanceof Map) {
                params.putAll((Map) parameter);
            } else {
                Map parameterObject = null;
                try {
                    parameterObject = PropertyUtils.describe(parameter);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if(parameterObject!=null)
                    params.putAll(parameterObject);
            }
        }
        return params;
    }
}